#include <kew/c-vm.h>

/*
 * Stack-related functions, particularly backtrace printing and chaining
 * various special handlers onto the C stack.
 *
 * The target address must be within the section of stack attached to the VM.
 * i.e. to the frame of a call made from somewhere within kew_enter_vm for that
 * thread.
 */

void kew_stack_unwind(KewDynamicEnvironment *dynamic_env, gpointer target_address)
{
    /* FIXME: this assumes stack grows downwards (and should this be <= ?) */
    
    while (dynamic_env->top_ensured_stack_frame < target_address) {
        
        while (dynamic_env->top_call_frame < dynamic_env->top_ensured_stack_frame)
            dynamic_env->top_call_frame = dynamic_env->top_call_frame->next;
            
        (*dynamic_env->top_ensured_stack_frame->callback)(dynamic_env, dynamic_env->top_ensured_stack_frame->data);
        dynamic_env->top_ensured_stack_frame = dynamic_env->top_ensured_stack_frame->next;
    }
}


/* Caller frees result
 * FIXME: this builds output quite inefficiently, but it should rarely be called */
GString *kew_stack_call(KewDynamicEnvironment *dynamic_env)
{
    KewCallFrame *frame = dynamic_env->top_call_frame;
    unsigned number = 0;
    /* FIXME: this relies on string behaviour I haven't tested! So it probably doesn't work */
    GString *trace = g_string_new("");
    
    while (frame < dynamic_env->bottom_frame) {
        g_string_append_printf(trace, "#%u  @%s\n", number++, frame->source_point);
        frame = frame->next;
    }
    
    return trace;
}

